#include <osg/Group>
#include <osg/Light>
#include <osg/LightSource>
#include <osg/Material>
#include <osg/ShapeDrawable>
#include <osg/Geode>
#include <osgViewer/Viewer>
#include <osg/NodeCallback>


class UpdateLightDirectionCallback : public osg::NodeCallback {
public:
    UpdateLightDirectionCallback(osg::Light* light, osgViewer::Viewer* viewer)
        : _light(light), _viewer(viewer) {}

    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) override {
        // 获取相机的视角方向
        osg::Matrixd viewMatrix = _viewer->getCamera()->getViewMatrix();
        osg::Vec3 direction = -viewMatrix.getRotate() * osg::Vec3(0.0f, 0.0f, -1.0f); // 取相机的朝前方向

        // 更新光源方向
        _light->setPosition(osg::Vec4(direction, 0.0f)); // w = 0 表示平行光

        // 调用基类回调
        traverse(node, nv);
    }

protected:
    osg::observer_ptr<osg::Light> _light; // 使用 observer_ptr 避免循环引用
    osg::observer_ptr<osgViewer::Viewer> _viewer;
};


int main() {
    osg::ref_ptr<osg::Group> root = new osg::Group();

    // 创建平行光源
    osg::ref_ptr<osg::Light> directionalLight = new osg::Light();
    directionalLight->setLightNum(0);
    directionalLight->setPosition(osg::Vec4(1.0f, -1.0f, -1.0f, 0.0f));
    directionalLight->setDiffuse(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
    directionalLight->setSpecular(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
    directionalLight->setAmbient(osg::Vec4(0.2f, 0.2f, 0.2f, 1.0f));

    osg::ref_ptr<osg::LightSource> lightSource = new osg::LightSource();
    lightSource->setLight(directionalLight);
    root->addChild(lightSource);

    // 创建一个立方体
    osg::ref_ptr<osg::Geode> cubeGeode = new osg::Geode();
    cubeGeode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f, 0.0f, 0.0f), 2.0f)));

    // 设置材质
    osg::ref_ptr<osg::Material> material = new osg::Material();
    material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0.8f, 0.5f, 0.2f, 1.0f));
    material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
    material->setShininess(osg::Material::FRONT_AND_BACK, 64.0f);
    cubeGeode->getOrCreateStateSet()->setAttributeAndModes(material, osg::StateAttribute::ON);

    root->addChild(cubeGeode);

    // 创建 Viewer
    osgViewer::Viewer viewer;
    viewer.setSceneData(root);

    // 设置光源的更新回调
    lightSource->setUpdateCallback(new UpdateLightDirectionCallback(directionalLight, &viewer));

    return viewer.run();
}


